package BioClusterAction;

import BioClusterForm.BioClusterHomeForm;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import java.io.InputStreamReader;

import java.io.StringReader;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;


/******************* your biojava imports **********************/
import org.biojava.bio.symbol.Alphabet;
import org.biojava.bio.BioException;
import org.biojava.bio.symbol.AlphabetManager;

import org.biojavax.SimpleNamespace;
import org.biojavax.bio.seq.RichSequence;
import org.biojavax.bio.seq.RichSequenceIterator;

/******************* your biojava imports **********************/
public class


BioClusterHomeAction extends Action {
    /**This is the main action called from the Struts framework.
     * @param mapping The ActionMapping used to select this instance.
     * @param form The optional ActionForm bean for this request.
     * @param request The HTTP Request we are processing.
     * @param response The HTTP Response we are processing.
     */
    public static final

    String projectLink = "C:\\Users\\Erasmus\\";
    /* Browse button for input file for users to submit fasta file and throws error if wrong input is submitted*/

    public ActionForward execute(ActionMapping mapping, ActionForm form, 
                                 HttpServletRequest request, 
                                 HttpServletResponse response) throws IOException, 
                                                                      ServletException, 
                                                                      FileNotFoundException, 
                                                                      BioException {
        BioClusterHomeForm bioClusterHomeForm = (BioClusterHomeForm)form;
        FormFile formFileBioCluster = 
            bioClusterHomeForm.getBioClusterHomeFileName();
        if (!formFileBioCluster.getFileName().endsWith(".fasta")) {
            ActionErrors actionerrors = new ActionErrors();
            actionerrors.add(ActionErrors.GLOBAL_ERROR, 
                             new ActionError("file.error"));
            saveErrors(request, actionerrors);
            return mapping.findForward("failure");
        }
        /*Parses the input fasta file to separate out the annotation from the sequence information using Biojava*/
        //System.out.println(formFileBioCluster.getContentType());
        byte[] byteFileBioCluster = formFileBioCluster.getFileData();
        String strFileBioCluster = new String(byteFileBioCluster);
        HashMap mapOfInputFastaFile = new HashMap();
        HashMap mappingNumberWithAccessionNo = new HashMap();
        BufferedReader br = 
            new BufferedReader(new InputStreamReader(formFileBioCluster.getInputStream()));
        Alphabet alpha = AlphabetManager.alphabetForName("PROTEIN");
        SimpleNamespace ns = new SimpleNamespace("biojava");
        RichSequenceIterator iterator = 
            RichSequence.IOTools.readFasta(br, alpha.getTokenization("token"), 
                                           ns);
        while (iterator.hasNext()) {
            RichSequence rec = iterator.nextRichSequence();
            String accessionNumber = rec.getAccession();
            //System.out.println(accessionNumber);
            String description = rec.getDescription();
            //System.out.println(description);
            String sequence = rec.seqString();
            //System.out.println(sequence);
            String[] descAndSeq = { description, sequence };
            mapOfInputFastaFile.put(accessionNumber, descAndSeq);
        }


        /*Creates a folder for each fasta input job submitted by the user*/
        String fileNameInput = formFileBioCluster.getFileName();
        //System.out.println(fileNameInput);
        Random randomGenerator = new Random();
        int randomInt = randomGenerator.nextInt(100000);
        String rString = Integer.toString(randomInt);
        String folderName = rString.concat(fileNameInput);
        File fastaFileToSave = new File(fileNameInput);
        try {
            FileWriter fstream = new FileWriter(fastaFileToSave);
            BufferedWriter out = new BufferedWriter(fstream);
            out.write(strFileBioCluster);
            out.close();
        } catch (Exception e) { //Catch exception if any
            System.err.println("Error: " + e.getMessage());
        }
        /*Call to the Python process and check for the input parameters passed to the Python process*/
        System.out.print("BEFORE SENDING PARAMS TO PYTHON SCRIPT - filename " + 
                         fileNameInput + " projlink - " + projectLink + 
                         " folderName " + folderName);
        ProcessBuilderTest processBuiderTest = 
            new ProcessBuilderTest("python ", "clusterscript.py", 
                                   "cluster.config", fileNameInput, folderName, 
                                   projectLink);
        processBuiderTest.startProcess();
        folderName = folderName + "\\";
        /*Retrieves the .cblast.tab file to compare and display the clustering results on the webpage*/
        try {
            FileReader tabFileToRead = 
                new FileReader(projectLink + folderName + fileNameInput + 
                               ".cblast.tab");
            System.out.println(projectLink + folderName + fileNameInput + 
                               ".cblast.tab");
            BufferedReader buff1 = new BufferedReader(tabFileToRead);
            String contentsOfTabFile = new String();
            boolean eof = false;
            while (!eof) {
                String tempLine = buff1.readLine();
                if (tempLine == null) {
                    eof = true;
                } else {
                    contentsOfTabFile = contentsOfTabFile + "\n" + tempLine;
                    eof = false;
                }
            }
            buff1.close();
            String arrayOfContentsOfTabFile[] = contentsOfTabFile.split("\n");
            for (int tabCount = 3; tabCount < arrayOfContentsOfTabFile.length; 
                 tabCount++) {
                String[] splitForward = 
                    arrayOfContentsOfTabFile[tabCount].split(" ");
                String initiatorNo = splitForward[0];
                String AccFromTabFile = ">" + splitForward[1];
                //System.out.println("InitiatorNumber:" + initiatorNo);
                //System.out.println("Header " + AccFromTabFile);
                BufferedReader br1 = 
                    new BufferedReader(new StringReader(AccFromTabFile));
                Alphabet alpha1 = AlphabetManager.alphabetForName("PROTEIN");
                SimpleNamespace ns1 = new SimpleNamespace("biojava");
                RichSequenceIterator iterator1 = 
                    RichSequence.IOTools.readFasta(br1, 
                                                   alpha1.getTokenization("token"), 
                                                   ns1);
                while (iterator1.hasNext()) {
                    RichSequence rec1 = iterator1.nextRichSequence();
                    String accessionNoFromTabFile = rec1.getAccession();
                    //System.out.println("Parsed acc no.:" + accessionNoFromTabFile);
                    mappingNumberWithAccessionNo.put(initiatorNo, 
                                                     accessionNoFromTabFile);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        File folderAccess = new File(projectLink + folderName);
        File[] listOfFiles = folderAccess.listFiles();
        HashMap hashMapListOfFiles = new HashMap();
        for (int iCount = 0; iCount < listOfFiles.length; iCount++) {
            if (listOfFiles[iCount].getName().contains(".cl")) {
                try {
                    FileReader fileToRead = 
                        new FileReader(projectLink + folderName + 
                                       listOfFiles[iCount].getName());
                    BufferedReader buff = new BufferedReader(fileToRead);
                    String contentsOfFile = new String();
                    boolean eof = false;
                    while (!eof) {
                        String tempLine = buff.readLine();
                        if (tempLine == null) {
                            eof = true;
                        } else {
                            contentsOfFile = contentsOfFile + "\n" + tempLine;
                            eof = false;
                        }
                    }
                    buff.close();
                    //System.out.println(contentsOfFile);
                    HashMap joinFilesWithAccessionMap = new HashMap();
                    String linesOfCLFiles[] = contentsOfFile.split("\n");
                    ArrayList subValuesOfRecords = new ArrayList();
                    for (int iCount1 = 1; iCount1 < linesOfCLFiles.length; 
                         iCount1++) {
                        subValuesOfRecords = new ArrayList();
                        String tabSeperate[] = new String[50];
                        if (linesOfCLFiles[iCount1].contains("\t")) {
                            tabSeperate = linesOfCLFiles[iCount1].split("\t");
                            for (int jCount = 0; jCount < tabSeperate.length; 
                                 jCount++) {
                                String accessionNo = 
                                    (String)mappingNumberWithAccessionNo.get(tabSeperate[jCount]);
                                subValuesOfRecords.add(accessionNo);
                            }
                        } else {
                            tabSeperate[0] = linesOfCLFiles[iCount1];
                            String accessionNo = 
                                (String)mappingNumberWithAccessionNo.get(tabSeperate[0]);
                            subValuesOfRecords.add(accessionNo);
                        }
                        joinFilesWithAccessionMap.put(tabSeperate[0], 
                                                      subValuesOfRecords);
                    }
                    hashMapListOfFiles.put(listOfFiles[iCount].getName(), 
                                           joinFilesWithAccessionMap);
                    /*Retrieving information from each inflation factor file */
                    String fileNamesInAsc[] = new String[12];
                    fileNamesInAsc[0] = "I50.cl";
                    fileNamesInAsc[1] = "I41.cl";
                    fileNamesInAsc[2] = "I36.cl";
                    fileNamesInAsc[3] = "I32.cl";
                    fileNamesInAsc[4] = "I30.cl";
                    fileNamesInAsc[5] = "I24.cl";
                    fileNamesInAsc[6] = "I22.cl";
                    fileNamesInAsc[7] = "I20.cl";
                    fileNamesInAsc[8] = "I18.cl";
                    fileNamesInAsc[9] = "I16.cl";
                    fileNamesInAsc[10] = "I14.cl";
                    fileNamesInAsc[11] = "I12.cl";

                    request.getSession().setAttribute("fileNamesInAsc", 
                                                      fileNamesInAsc);
                    request.getSession().setAttribute("fileNameFromAction", 
                                                      fileNamesInAsc[0]);
                    request.getSession().setAttribute("hashMapListOfFiles", 
                                                      hashMapListOfFiles);
                    request.getSession().setAttribute("mapOfInputFastaFile", 
                                                      mapOfInputFastaFile);
                    request.getSession().setAttribute("offset", "1");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return mapping.findForward("success");
    }

}

